package org.tamal.classinfo;

import java.util.ArrayList;
import java.util.List;

/**
 * This class contains utility methods used in this package.
 * @author Tamal Kanti Nath
 */
public final class Util {

    private static final String COMMA = ", ";

    private Util() {
    }

    /**
     * Formats a field or method name by a descriptor.
     * @param name the field/method name
     * @param descriptor the descriptor
     * @return the name formatted by the descriptor
     */
    static String formatNameType(String name, String descriptor) {
        List<String> list = new ArrayList<>();
        boolean isMethod = false;
        int i = 0;
        int d = 0;
        while (i < descriptor.length()) {
            String param = null;
            switch (descriptor.charAt(i)) {
            case 'B':
                param = "byte";
                break;
            case 'C':
                param = "char";
                break;
            case 'D':
                param = "double";
                break;
            case 'F':
                param = "float";
                break;
            case 'I':
                param = "int";
                break;
            case 'J':
                param = "long";
                break;
            case 'L':
                StringBuilder sb = new StringBuilder();
                while (descriptor.charAt(++i) != ';') {
                    sb.append(descriptor.charAt(i));
                }
                param = sb.toString();
                break;
            case 'S':
                param = "short";
                break;
            case 'V':
                param = "void";
                break;
            case 'Z':
                param = "boolean";
                break;
            case '[':
                ++d;
                break;
            case '(':
            case ')':
                isMethod = true;
                break;
            default:
                throw new ClassFormatException("invalid descriptor");
            }
            if (param != null) {
                while (d > 0) {
                    param += "[]";
                    --d;
                }
                list.add(param);
            }
            ++i;
        }
        StringBuilder buf = new StringBuilder();
        buf.append(list.get(list.size() - 1)).append(" ").append(name);
        if (isMethod) {
            buf.append("(");
            for (i = 0; i < list.size() - 1; ++i) {
                buf.append(list.get(i)).append(COMMA);
            }
            if (list.size() > 1) {
                buf.delete(buf.length() - 2, buf.length());
            }
            buf.append(")");
        }
        return buf.toString();
    }

    /**
     * Inserts class name to field or method to make the field or method fully
     * qualified.
     * @param cls the fully qualified class name
     * @param fm a field or a method
     * @return A field or method prefixed with class name
     */
    static String insertClass(String cls, String fm) {
        if (fm.startsWith("void <init>")) {
            return cls + fm.substring(11);
        }
        int idx = fm.indexOf(' ') + 1;
        return fm.substring(0, idx) + cls + "." + fm.substring(idx);
    }
}
